package no.hib.mod250.chat.client.view;

import java.util.ArrayList;
import java.util.List;

import no.hib.mod250.chat.client.controller.ChatController;
import no.hib.mod250.chat.client.i18.ChatConstants;
import no.hib.mod250.chat.client.model.Model;
import no.hib.mod250.chat.client.model.Model.Message;
import no.hib.mod250.chat.client.service.ChatService;
import no.hib.mod250.chat.client.util.ObjectWithEvent;
import no.hib.mod250.chat.client.util.R;
import no.hib.mod250.chat.client.util.Util;
import no.hib.mod250.chat.client.view.View.DataObserver;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.StackPanel;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class UsersView extends View implements DataObserver,
		ChatView.MessageClickObserver {

	// CLASSES

	private static class UserView {

		private static class Images {
			public static Image available() {
				return new Image("images/user_available.png");
			}

			public static Image busy() {
				return new Image("images/user_busy.png");
			}
		}

		private UserView() {

		}

		public static void doDraw(final Model.User user, final FlexTable table) {
			Image avatar = Util.Gravatar.generate(user.getEmail(), 20);

			Image status = null;
			switch (user.getState()) {
			case Model.User.STATE_BUSY:
				status = Images.busy();
				break;

			default:
				status = Images.available();
				break;
			}

			int i = table.getRowCount();
			table.setWidget(i, 0, avatar);
			table.setWidget(i, 1, new HTML(user.getNickname()));
			table.setWidget(i, 2, status);
		}
	}

	private class SettingToggle extends ToggleButton implements
			ObjectWithEvent.Listener<Boolean>, ValueChangeHandler<Boolean> {

		private Grid grdFaceUp = new Grid(1, 2);
		private Grid grdFaceDown = new Grid(1, 2);
		private ObjectWithEvent<Boolean> object;

		public SettingToggle(String text, Image up, Image down,
				ObjectWithEvent<Boolean> object) {
			// Set variables
			this.object = object;

			// Grid face
			grdFaceUp.setWidget(0, 0, up);
			grdFaceUp.setText(0, 1, text);
			grdFaceUp.setWidth("100%");
			grdFaceDown.setWidget(0, 0, down);
			grdFaceDown.setText(0, 1, text);
			grdFaceDown.setWidth("100%");

			// Initialize faces
			getDownFace().setHTML(grdFaceDown.toString());
			getUpFace().setHTML(grdFaceUp.toString());

			// Set value depending on Object state
			setValue(!object.getObject(), true);

			// Add toggle listener
			addValueChangeHandler(this);

			// Add object listener
			object.addListener(this);
		}

		@Override
		public void onChanged(Boolean value) {
			setValue(!value, true);
		}

		@Override
		public void onValueChange(ValueChangeEvent<Boolean> event) {
			object.setObject(!event.getValue());
		}
	}

	public class MessageMediaView {

		private final Panel panel;

		public MessageMediaView(final Panel panel) {
			this.panel = panel;
		}

		private Widget getClose() {
			Anchor anchor = new Anchor("close", "#");
			anchor.addClickHandler(new ClickHandler() {

				@Override
				public void onClick(ClickEvent event) {
					doCloseMedia();
				}
			});

			return anchor;
		}

		private List<Widget> getMedia(final String message) {
			return Util.URI.MediaParser.parse(message);
		}

		public void doDraw(final Model.Message message) {
			Grid header = new Grid(1, 1);
			header.setWidget(0, 0, getClose());
			header.setWidth("100%");
			panel.add(header);

			// Add each media element to panel
			List<Widget> mediaList = getMedia(message.getMessage());
			for (Widget widget : mediaList) {
				//widget.setWidth("" + panel.getOffsetWidth() + "px");
				widget.setWidth("100%");
				panel.add(widget);
			}

		}
	}

	// /CLASSES

	// VARIABLES

	// ... VIEW

	private final VerticalPanel panel = new VerticalPanel();
	private final FlexTable usersTable = new FlexTable();
	private List<Model.User> users = new ArrayList<Model.User>();
	private SettingToggle tglbtnPauseTimer;
	private SettingToggle tglbtnUpdateWhenIdle;
	private final VerticalPanel verticalPanel_1 = new VerticalPanel();
	private final FocusPanel focusPanel = new FocusPanel();
	private final ScrollPanel scrollPanel = new ScrollPanel();
	private final StackPanel stackPanel = new StackPanel();
	private final Button btnDeleteMessages = new Button();

	// ... /VIEW

	private static ChatConstants.Users usersConstants = GWT
			.create(ChatConstants.Users.class);

	// /VARIABLES

	// CONSTRUCTOR

	public UsersView(ChatController controller) {
		super(controller);

		controller.addDataObserver(this);
		controller.addMessageClickObserver(this);

		initWidget(panel);

		doDraw();
		doEvents();
	}

	// /CONSTRUCTOR

	// FUNCTIONS

	@Override
	protected void doDraw() {
		// Panel
		panel.setStyleName(R.Class.Users.users);
		
		// Stack panel
		panel.add(stackPanel);
		panel.setCellHorizontalAlignment(stackPanel,
				HasHorizontalAlignment.ALIGN_CENTER);
		panel.setCellWidth(stackPanel, "100%");
		stackPanel.setSize("90%", "");

		// Users
		stackPanel.add(usersTable, usersConstants.users());
		usersTable.setSize("100%", "100%");

		// SETTINGS
		
		VerticalPanel settingsPanel = new VerticalPanel();
		settingsPanel.setWidth("100%");
		stackPanel.add(settingsPanel, usersConstants.settings());

		// Pause timer
		tglbtnPauseTimer = new SettingToggle(usersConstants
				.settingsTimersRunning(), new Image(R.Image.toggle_on),
				new Image(R.Image.toggle_off), getController()
						.getTimerUpdateEnabled());
		settingsPanel.add(tglbtnPauseTimer);
		settingsPanel.setCellWidth(tglbtnPauseTimer, "100%");
		
		// Update when idle
		tglbtnUpdateWhenIdle = new SettingToggle(usersConstants
				.settingsUpdateWhileBusy(), new Image(R.Image.toggle_on),
				new Image(R.Image.toggle_off), getController()
						.getUpdateWhileBusy());
		settingsPanel.add(tglbtnUpdateWhenIdle);
		settingsPanel.setCellWidth(tglbtnUpdateWhenIdle, "100%");

		// Delete Messages
		btnDeleteMessages.setText(usersConstants.deleteMessages());
		btnDeleteMessages.setWidth("100%");
		settingsPanel.add(btnDeleteMessages);
		settingsPanel.setCellWidth(btnDeleteMessages, "100%");
		btnDeleteMessages.setVisible(false);

		// /SETTINGS
		
		// Media viewer
		panel.add(scrollPanel);
		panel.setCellHorizontalAlignment(scrollPanel,
				HasHorizontalAlignment.ALIGN_CENTER);
		scrollPanel.setStyleName(R.Class.Users.mediaViewer);
		scrollPanel.setSize("90%", "");
		scrollPanel.setWidget(focusPanel);
		focusPanel.setSize("", "");
		focusPanel.setWidget(verticalPanel_1);
		verticalPanel_1.setSize("100%", "");
		scrollPanel.setVisible(false);
	}

	private void doEvents() {
		// Focus panel
		focusPanel.addKeyUpHandler(new KeyUpHandler() {

			@Override
			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
					doCloseMedia();
				}
			}
		});

		// Delete Messages
		btnDeleteMessages.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				getController().doMessagesDelete();
			}
		});
	}

	private void doCloseMedia() {
		scrollPanel.setVisible(false);
		stackPanel.setVisible(true);
	}

	public void doDrawUpdate() {
		usersTable.removeAllRows();

		for (Model.User user : users) {
			UserView.doDraw(user, usersTable);
		}
	}

	@Override
	public void onDataResult(ChatService.Result result) {

		// Users
		if (result.getUsers() != null) {
			users = result.getUsers();
			doDrawUpdate();
		}
		
		// Delete messages
		if (result.getUser() != null)
		{
			btnDeleteMessages.setVisible(result.getUser().isAdmin());
		}

	}

	@Override
	public void onMessageClick(Message message) {

		verticalPanel_1.clear();

		MessageMediaView messageMediaView = new MessageMediaView(
				verticalPanel_1);
		messageMediaView.doDraw(message);

		scrollPanel.setVisible(true);
		stackPanel.setVisible(false);
	}

	// /FUNCTIONS

}
